package httpUtil;


import android.support.annotation.NonNull;

import android.text.TextUtils;
import android.util.Log;


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ConnectException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;

import okhttp3.Response;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
import utils.JsonUtil;


public class Http {

    private static final MediaType MEDIA_TYPE = MediaType.parse("application/octet-stream");
    public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
    private static final String TAG = "zjt";
    private static final int CODE_OK = 200;
    static OkHttpClient client;
//    public static String address = "http://192.168.1.115:8088";
//    public static String api = "/child";
//
//    public static String getApi() {
//        return address + api;
//    }

    @NonNull
    public static OkHttpClient getClient() {
        if (client != null) {
            return client;
        } else {

            client = new OkHttpClient.Builder()
                    .connectTimeout(60, TimeUnit.SECONDS)
                    .writeTimeout(60, TimeUnit.SECONDS)
                    .readTimeout(60, TimeUnit.SECONDS)
                    .addInterceptor(appIntercepter)
                    .build();


            return client;

        }

    }


    public static Observable<Res> post(String api, @NonNull Object object) {
        return dataObservable(api, object);

    }

    public static Observable<Res> sycn(String api, @NonNull Object object) {
        return sycnPost(api, object);

    }

    private static Observable<Res> sycnPost(String api, Object object) {
        return Observable.create(new Observable.OnSubscribe<Res>() {
            @Override
            public void call(Subscriber<? super Res> subscribe) {
                try {
                    RequestBody requestBody = RequestBody.create(MEDIA_TYPE_JSON, JsonUtil.toJson(object));
                    Request request = new Request.Builder()
                            .url(Api.getUrlRoot() + api)
                            .post(requestBody)
                            .build();
                    Call call = getClient().newCall(request);
                    okhttp3.Response response = call.execute();
                    if (response.isSuccessful()) {
                        if (!subscribe.isUnsubscribed()) {
                            String string = response.body().string();
                            Res res = JsonUtil.getObject(string, Res.class);
                            if (res.getCode() == CODE_OK) {
                                subscribe.onNext(res);
                            } else {
                                subscribe.onError(new Throwable("请求出错"));

                            }

                        }

                    } else {
                        if (!subscribe.isUnsubscribed()) {
                            subscribe.onError(new Throwable("请求出错"));
                        }
                    }
                } catch (ConnectException ex) {
                    if (!subscribe.isUnsubscribed()) {
                        subscribe.onError(ex);

                    }
                } catch (IOException e) {
                    if (!subscribe.isUnsubscribed()) {
                        subscribe.onError(e);

                    }

                }

            }
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());

    }

    public static Observable<Res> list(String api, @NonNull Object object) {
        return ListPageObservable(api, object);

    }


    public static Observable<Res> postForm(String api, String parms, @NonNull final Map<String, Object> map, List<File> files) {
        return Observable.create(
                new Observable.OnSubscribe<Res>() {
                    @Override
                    public void call(Subscriber<? super Res> subscribe) {
                        try {
                    /* form的分割线,自己定义 */
                            String boundary = "xx--------------------------------------------------------------xx";

                            MultipartBody.Builder builder = new MultipartBody.Builder(boundary).setType(MultipartBody.FORM);
//                    for (String key : map.keySet()) {
//                        builder.addFormDataPart(key, map.get(key).toString());
//                    }

                            builder.addFormDataPart(parms, JsonUtil.toJson(map));

                            for (int i = 0; i < files.size(); i++) {
                                builder.addFormDataPart("file" + i, files.get(i).getName(), RequestBody.create(MEDIA_TYPE, files
                                        .get(i)));
                            }

                            Request request = new Request.Builder()
                                    .url(Api.getUrlRoot() + api)
                                    .post(builder.build())
                                    .build();
                            Call call = getClient().newCall(request);
                            okhttp3.Response response = call.execute();
                            if (response.isSuccessful()) {
                                if (!subscribe.isUnsubscribed()) {
                                    String string = response.body().string();
                                    Res res = JsonUtil.getObject(string, Res.class);
                                    if (res.getCode() == CODE_OK) {
                                        subscribe.onNext(res);
                                        subscribe.onCompleted();
                                    } else {
                                        subscribe.onError(new Throwable("请求出错"));

                                    }
                                }

                            } else {
                                subscribe.onError(new Throwable("请求出错"));

                            }

                        } catch (ConnectException ex) {
                            if (!subscribe.isUnsubscribed()) {
                                subscribe.onError(ex);

                            }
                        } catch (IOException e) {
                            if (!subscribe.isUnsubscribed()) {
                                subscribe.onError(e);

                            }
                        }

                    }

                }
        ).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());


    }

    public static Observable<Res> postFormWithJson(String api, String parms, Object o, Map<String, File> files) {
        return Observable.create(
                new Observable.OnSubscribe<Res>() {
                    @Override
                    public void call(Subscriber<? super Res> subscribe) {
                        try {
                    /* form的分割线,自己定义 */
                            String boundary = "xx--------------------------------------------------------------xx";

                            MultipartBody.Builder builder = new MultipartBody.Builder(boundary).setType(MultipartBody.FORM);


                            builder.addFormDataPart(parms, JsonUtil.toJson(o));


                            for (String key : files.keySet()) {
                                builder.addFormDataPart(key, files.get(key).getName(), RequestBody.create(MEDIA_TYPE, files
                                        .get(key)));
                            }

                            Request request = new Request.Builder()
                                    .url(Api.getUrlRoot() + api)
                                    .post(builder.build())
                                    .build();
                            Call call = getClient().newCall(request);
                            okhttp3.Response response = call.execute();
                            if (response.isSuccessful()) {
                                if (!subscribe.isUnsubscribed()) {
                                    String string = response.body().string();
                                    Res res = JsonUtil.getObject(string, Res.class);
                                    if (res.getCode() == CODE_OK) {
                                        subscribe.onNext(res);

                                    } else {
                                        subscribe.onError(new Throwable("请求出错"));

                                    }
                                }

                            } else {
                                subscribe.onError(new Throwable("请求出错"));

                            }

                        } catch (ConnectException ex) {
                            if (!subscribe.isUnsubscribed()) {
                                subscribe.onError(ex);

                            }
                        } catch (IOException e) {
                            if (!subscribe.isUnsubscribed()) {
                                subscribe.onError(e);

                            }
                        }

                    }

                }
        ).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());


    }

//    public static Observable<Res> postForm(String api, String parms, @NonNull Object object, List<File> files) {
//        return Observable.create(
//                new Observable.OnSubscribe<Res>() {
//                    @Override
//                    public void call(Subscriber<? super Res> subscribe) {
//                        try {
//                    /* form的分割线,自己定义 */
//                            String boundary = "xx--------------------------------------------------------------xx";
//
//                            MultipartBody.Builder builder = new MultipartBody.Builder(boundary).setType(MultipartBody.FORM);
////                    for (String key : map.keySet()) {
////                        builder.addFormDataPart(key, map.get(key).toString());
////                    }
//
//                            builder.addFormDataPart(parms, JsonUtil.toJson(object));
//
//                            for (int i = 0; i < files.size(); i++) {
//                                builder.addFormDataPart("file" + i, files.get(i).getName(), RequestBody.create(MEDIA_TYPE, files
//                                        .get(i)));
//                            }
//
//                            Request request = new Request.Builder()
//                                    .url(Api.getUrlRoot() + api)
//                                    .post(builder.build())
//                                    .build();
//                            Call call = getClient().newCall(request);
//                            okhttp3.Response response = call.execute();
//                            if (response.isSuccessful()) {
//                                if (!subscribe.isUnsubscribed()) {
//                                    String string = response.body().string();
//                                    Log.d(TAG, string);
//                                    JSONObject jsonObject = new JSONObject(string);
//                                    int code = jsonObject.getInt("Code");
//                                    String data = jsonObject.getString("Content");
//                                    Res res = new Res();
//                                    res.setCode(code);
//                                    res.setContent(data);
//                                    if (code == CODE_OK) {
//                                        subscribe.onNext(res);
//                                        subscribe.onCompleted();
//                                    } else subscribe.onError(new Throwable("请求出错"));
//
//                                }
//
//                            } else {
//                                subscribe.onError(new Throwable("请求出错"));
//
//                            }
//
//                        } catch (ConnectException ex) {
//                            if (!subscribe.isUnsubscribed()) {
//                                subscribe.onError(ex);
//
//                            }
//                        } catch (JSONException exception) {
//                            if (!subscribe.isUnsubscribed()) {
//                                subscribe.onError(exception);
//
//                            }
//                        } catch (IOException e) {
//                            if (!subscribe.isUnsubscribed()) {
//                                subscribe.onError(e);
//
//                            }
//                        }
//
//                    }
//
//                }
//        ).subscribeOn(Schedulers.io())
//                .observeOn(AndroidSchedulers.mainThread());
//
//
//    }

    static OkHttpClient.Builder builder;

    public static OkHttpClient.Builder getBuild() {
        if (builder == null) {

            builder = new OkHttpClient.Builder()
                    .connectTimeout(30, TimeUnit.SECONDS)
                    .writeTimeout(60, TimeUnit.SECONDS)
                    .readTimeout(60, TimeUnit.SECONDS)

            ;
        }
        return builder;
    }


    public static Observable<String> test(String api, @NonNull Object object) {
        return Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscribe) {
                try {
                    RequestBody requestBody = RequestBody.create(MEDIA_TYPE_JSON, JsonUtil.toJson(object));
                    Request request = new Request.Builder()
                            .url(Api.getUrlRoot() + api)
                            .post(requestBody)
                            .build();
                    Call call = getClient().newCall(request);
                    okhttp3.Response response = call.execute();

                    if (!subscribe.isUnsubscribed()) {
                        if (response.isSuccessful()) {
                            String string = response.body().string();
                            Log.d(TAG, string);
                            subscribe.onNext(string);
                            subscribe.onCompleted();
                        }
                    }
                } catch (ConnectException ex) {
                    if (!subscribe.isUnsubscribed()) {
                        subscribe.onError(ex);
                    }
                } catch (IOException e) {
                    if (!subscribe.isUnsubscribed()) {
                        subscribe.onError(e);
                    }

                }

            }
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());


    }


    private static Observable<Res> dataObservable(final String api, @NonNull final Object object) {
        return Observable.create(new Observable.OnSubscribe<Res>() {
            @Override
            public void call(Subscriber<? super Res> subscribe) {
                try {
                    RequestBody requestBody = RequestBody.create(MEDIA_TYPE_JSON, JsonUtil.toJson(object));
                    Request request = new Request.Builder()
                            .url(Api.getUrlRoot() + api)
                            .post(requestBody)
                            .build();
                    Call call = getClient().newCall(request);
                    okhttp3.Response response = call.execute();
                    if (response.isSuccessful()) {
                        if (!subscribe.isUnsubscribed()) {
                            String string = response.body().string();
                            Res res = JsonUtil.getObject(string, Res.class);
                            if (res.getCode() == CODE_OK) {
                                subscribe.onNext(res);
                            } else {
                                subscribe.onError(new Throwable("请求出错"));

                            }

                        }

                    } else {
                        if (!subscribe.isUnsubscribed()) {
                            subscribe.onError(new Throwable("请求出错"));
                        }
                    }
                } catch (ConnectException ex) {
                    if (!subscribe.isUnsubscribed()) {
                        subscribe.onError(ex);

                    }
                } catch (IOException e) {
                    if (!subscribe.isUnsubscribed()) {
                        subscribe.onError(e);

                    }

                }

            }
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }


//    public static Observable<Res> login(@NonNull final Map<String, Object> map) {
//        return Observable.create(new Observable.OnSubscribe<Res>() {
//            @Override
//            public void call(Subscriber<? super Res> subscribe) {
//
//
//                    FormBody.Builder builder = new FormBody.Builder();
//                    for (String key : map.keySet()) {
//                        builder.add(key, map.get(key).toString());
//                    }
//                    Request request = new Request.Builder()
//                            .url(Api.getUrlRoot() + "/applogin")
//                            .post(builder.build())
//                            .build();
//
//                Response response = null;
//                try {
//                    response = getClient().newCall(request).  execute();
//                    if (!subscribe.isUnsubscribed()) {
//                        if (response.isSuccessful()) {
//                            String s=response.body().string();
//                            Log.d(TAG,s);
//                            Res res =JsonUtil.getObject(s,Res.class);
//                            if (res!=null&&res.getCode()==0){
//                                subscribe.onNext(res);
//                            }else {
//                                subscribe.onError(new Throwable(""));
//                            }
//
//                        } else {
//
//                                subscribe.onError(new Throwable("请求出错"));
//
//                        }
//                    }
//
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//
//
//
//            }
//        }).subscribeOn(Schedulers.io())
//                .observeOn(AndroidSchedulers.mainThread());
//    }

    private static Observable<Res> ListPageObservable(final String api, @NonNull final Object object) {
        return Observable.create(new Observable.OnSubscribe<Res>() {
            @Override
            public void call(Subscriber<? super Res> subscribe) {
                try {
                    RequestBody requestBody = RequestBody.create(MEDIA_TYPE_JSON, JsonUtil.toJson(object));
                    Request request = new Request.Builder()
                            .url(Api.getUrlRoot() + api)
                            .post(requestBody)
                            .build();
                    Call call = getClient().newCall(request);
                    okhttp3.Response response = call.execute();
                    if (response.isSuccessful()) {
                        if (!subscribe.isUnsubscribed()) {
                            String string = response.body().string();
                            Res res = JsonUtil.getObject(string, Res.class);
                            if (res.getCode() == CODE_OK) {
                                subscribe.onNext(res);
                                subscribe.onCompleted();
                            } else {
                                subscribe.onError(new Throwable("请求出错"));

                            }


                        }

                    } else {
                        if (!subscribe.isUnsubscribed()) {
                            subscribe.onError(new Throwable("请求出错"));
                        }
                    }
                } catch (ConnectException ex) {
                    if (!subscribe.isUnsubscribed()) {
                        subscribe.onError(ex);

                    }
                } catch (IOException e) {
                    if (!subscribe.isUnsubscribed()) {
                        subscribe.onError(e);

                    }

                }

            }
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }


    public static void downFile(String file, String target) {
        Request request = new Request.Builder()
                .url(file)
                .build();
        Call call = getClient().newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, okhttp3.Response response) throws IOException {
                InputStream is = null;
                byte[] buf = new byte[2048];
                int len = 0;
                FileOutputStream fos = null;

                try {
                    is = response.body().byteStream();
                    long total = response.body().contentLength();
                    File file = new File(target);
                    fos = new FileOutputStream(file);
                    long sum = 0;
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                        sum += len;
                        int progress = (int) (sum * 1.0f / total * 100);
                        Log.d("zjt", "progress=" + progress);

                    }
                    fos.flush();
                    Log.d("zjt", "文件下载成功");
                } catch (Exception e) {
                    Log.d("zjt", "文件下载失败");
                } finally {
                    try {
                        if (is != null)
                            is.close();
                    } catch (IOException e) {
                    }
                    try {
                        if (fos != null)
                            fos.close();
                    } catch (IOException e) {
                    }
                }
            }
        });


    }

    //应用拦截器：主要用于设置公共参数，头信息，日志拦截等,有点类似Retrofit的Converter
    private static Interceptor appIntercepter = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = processRequest(chain.request());
            Response response = processResponse(chain.proceed(request));
            return response;
        }
    };

    //访问网络之前，处理Request(这里统一添加了Cookie)
    private static Request processRequest(Request request) {
        String session = CacheManager.getSessionId();
        if (TextUtils.isEmpty(session))
            return request.newBuilder().build();
        else return request.newBuilder().addHeader("Cookie", session).build();
    }

    //访问网络之后，处理Response(这里没有做特别处理)
    private static Response processResponse(Response response) {
        return response;
    }


//    public static Observable<Boolean> getSessionId() {
//        return Observable.create(new Observable.OnSubscribe<Boolean>() {
//            @Override
//            public void call(Subscriber<? super Boolean> subscriber) {
//
//                Request request = new Request.Builder()
//                        .url(Api.getUrlRoot() + "/appsession")
//                        .build();
//
//                Response response = null;
//                try {
//                    response = getClient().newCall(request).execute();
//                    if (response.isSuccessful()) {
//                        Headers headers = response.headers();
//                        List<String> cookies = headers.values("Set-Cookie");
//                        String session = cookies.get(0);
//                        String s = session.substring(0, session.indexOf(";"));
//                        if (!TextUtils.isEmpty(s)) {
//
//                            CacheManager.setSessionId(s);
//                            subscriber.onNext(true);
//                        } else {
//                            subscriber.onError(new Throwable("没有session"));
//                        }
//                    } else {
//                        subscriber.onError(new Throwable("请求出错"));
//                    }
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//
//
//            }
//        }).subscribeOn(Schedulers.io())
//                .observeOn(AndroidSchedulers.mainThread());
//    }


}
